import hashlib

from ckeditor.fields import RichTextField
from django.conf import settings
from django.contrib.auth.hashers import make_password
from django.contrib.auth.models import AbstractUser
from django.db import models
from django.db.models.signals import pre_save, post_save
from django.dispatch import receiver
from django.utils.translation import gettext_lazy as _

from jiaozi.utils import hget_data, hset_data, int_value, model_data_from_cache, rsa_decrypt, rsa_encrypt, \
    pbkdf2_hmac_encrypt, convert_obj_to_dict


class WxHome(models.Model):
    logo_circular = models.ImageField(verbose_name=_('圆形 logo'), upload_to='media/main/%Y%m/', null=True, blank=True)
    logo_square = models.ImageField(verbose_name=_('方形 logo'), upload_to='media/main/%Y%m/', null=True, blank=True)
    image_1 = models.ImageField(verbose_name=_('图片1'), upload_to='media/main/%Y%m/', null=True, blank=True)
    image_2 = models.ImageField(verbose_name=_('图片2'), upload_to='media/main/%Y%m/', null=True, blank=True)
    image_3 = models.ImageField(verbose_name=_('图片3'), upload_to='media/main/%Y%m/', null=True, blank=True)
    image_4 = models.ImageField(verbose_name=_('图片4'), upload_to='media/main/%Y%m/', null=True, blank=True)
    image_5 = models.ImageField(verbose_name=_('图片5'), upload_to='media/main/%Y%m/', null=True, blank=True)
    vip_background = models.ImageField(
        verbose_name=_('VIP售卖背景图'), upload_to='media/main/%Y%m/', null=True, blank=True)
    activity_time = models.CharField(verbose_name=_('活动时间'), default='每周二19:00-每周四19:00', max_length=255)
    charge = models.CharField(verbose_name=_('运费'), default='￥0.00-30.00', max_length=255)
    is_active = models.BooleanField(verbose_name=_('开启'), default=True)
    datetime_created = models.DateTimeField(verbose_name=_('创建时间'), auto_now_add=True)
    datetime_updated = models.DateTimeField(verbose_name=_('更新时间'), auto_now=True)

    objects = models.Manager()

    class Meta:
        ordering = ['-id']
        verbose_name = _('首页配置')
        verbose_name_plural = verbose_name

    def __str__(self):
        return "{0} {1}".format(self.pk, self.logo_circular)


class WxUser(AbstractUser):
    # 重写用户模块，此用户模块用于登录后台管理系统
    mobile = models.CharField(verbose_name=_('手机号'), max_length=100, null=True, blank=True, unique=True)
    openid = models.CharField(verbose_name=_('微信小程序OpenID'), max_length=100, unique=True, null=True, blank=True)
    openid_gzh = models.CharField(verbose_name=_('微信公众号OpenID'), max_length=100, unique=True, null=True, blank=True)
    unionid = models.CharField(verbose_name='unionid', blank=True, max_length=255, null=True, unique=True)
    avatar_url = models.URLField(verbose_name=_('头像'), null=True, blank=True)
    nick_name = models.CharField(verbose_name=_('昵称'), max_length=100, blank=True, default="")
    gender = models.SmallIntegerField(
        verbose_name=_('性别'), choices=((1, '男'), (2, '女'), (0, '未知')), blank=True, default=0)
    language = models.CharField(verbose_name=_('语言'), max_length=100, null=True, blank=True)
    city = models.CharField(verbose_name=_('城市'), max_length=200, null=True, blank=True)
    province = models.CharField(verbose_name=_('省份'), max_length=200, null=True, blank=True)
    country = models.CharField(verbose_name=_('国家'), max_length=200, null=True, blank=True)
    date_of_birth = models.DateField(verbose_name=_('出生日期'), null=True, blank=True)
    vip_level = models.ForeignKey(
        'vip.VipLevel',
        null=True,
        blank=True,
        on_delete=models.SET_NULL,
        verbose_name=_('会员等级')
    )
    vip_start = models.DateTimeField(verbose_name=_('会员开始'), null=True, blank=True)
    vip_end = models.DateTimeField(verbose_name=_('会员结束'), null=True, blank=True)
    default_user_address = models.ForeignKey(
        'app.UserAddress',
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        verbose_name=_('默认地址')
    )
    desc = models.TextField(verbose_name=_('描述'), help_text='描述', max_length=2000, blank=True, default="")

    @property
    def user_point_data(self):
        # 获取用户的积分数据
        key_name = 'app_wx_user_user_point_data'
        data = hget_data(key_name, self.pk)
        if not data:
            user_point = UserPoint.objects.filter(
                user_id=self.pk
            ).order_by('-pk').values(
                'amount', 'amount_total', 'amount_current'
            ).first()
            if user_point:
                data = convert_obj_to_dict(user_point)
            else:
                data = {
                    'amount': 0,
                    'amount_total': 0,
                    'amount_current': 0,
                }
            hset_data(key_name, self.pk, data)
            data = hget_data(key_name, self.pk)
        return data

    def create_username_password(self):
        key = settings.SECRET_KEY
        if not self.username:
            if self.openid:
                self.username = hashlib.pbkdf2_hmac(
                    "sha256", getattr(self, 'openid').encode(encoding='utf-8'), key.encode(encoding='utf-8'), 10
                ).hex()
                raw_password = hashlib.pbkdf2_hmac(
                    "sha256", self.username.encode(), getattr(self, 'openid').encode(encoding='utf-8'), 10
                ).hex()
                self.password = make_password(raw_password)

    def add_point_record(self, amount, notes=''):
        # 添加用户积分更新数据
        UserPoint.objects.create(user_id=self.pk, amount=amount, notes=notes)

    class Meta(AbstractUser.Meta):
        swappable = 'AUTH_USER_MODEL'
        ordering = ['-id']
        verbose_name = '用户'
        verbose_name_plural = verbose_name

    def __str__(self):
        return '{} {}'.format(self.nick_name, self.mobile)


def get_user_info(wx_user_obj):
    res = convert_obj_to_dict(wx_user_obj, exclude=['password', 'user_permissions', 'is_anonymous'])
    return res


@receiver(pre_save, sender=WxUser)
def pre_save_wx_user(sender, instance, **kwargs):
    instance.create_username_password()


@receiver(post_save, sender=WxUser)
def post_save_wx_user(sender, instance, **kwargs):
    model_data_from_cache(sender, instance.pk, force_update=True)


class UserCardNumber(models.Model):
    user = models.ForeignKey(
        WxUser,
        on_delete=models.CASCADE,
        null=True,
        blank=True,
        verbose_name=_('关联用户')
    )
    name = models.CharField(verbose_name=_('姓名'), max_length=255)
    card_number_data = models.TextField(verbose_name=_('身份证-数据'), max_length=2000, null=True, blank=True)
    card_number_index = models.TextField(
        verbose_name=_('身份证-索引'), max_length=2000, null=True, blank=True, db_index=True)
    datetime_created = models.DateTimeField(verbose_name=_('创建时间'), auto_now_add=True)
    datetime_updated = models.DateTimeField(verbose_name=_('更新时间'), auto_now=True)

    def _get_card_number(self):
        """
        获取 card_number 的数据进行解密后返回
        :return: 解密后的数据
        """
        if self.card_number_data:
            return rsa_decrypt(self.card_number_data)
        else:
            return None

    def _set_card_number(self, card_number):
        """
        设置 card_number 的值
        :return: 加密后存储
        """
        self.card_number_data = rsa_encrypt(card_number)
        self.card_number_index = pbkdf2_hmac_encrypt(card_number)

    card_number = property(_get_card_number, _set_card_number)

    objects = models.Manager()

    class Meta:
        ordering = ['-id']
        verbose_name = _('身份信息')
        verbose_name_plural = verbose_name

    def __str__(self):
        return "{0}".format(
            self.user,
        )


class UserPoint(models.Model):
    user = models.ForeignKey(
        WxUser,
        on_delete=models.CASCADE,
        verbose_name=_('用户')
    )
    amount = models.IntegerField(verbose_name=_('积分变化'), default=0)
    amount_total = models.IntegerField(verbose_name=_('累计积分'), default=0, null=True, blank=True)
    amount_current = models.IntegerField(verbose_name=_('当前积分'), default=0, null=True, blank=True)
    notes = models.CharField(verbose_name=_('备注'), max_length=255, default='', null=True, blank=True)
    datetime_created = models.DateTimeField(verbose_name=_('创建时间'), auto_now_add=True)
    datetime_updated = models.DateTimeField(verbose_name=_('更新时间'), auto_now=True)

    objects = models.Manager()

    def update_amount(self):
        # 自动更新累计积分和当前积分
        pre_amount_total = 0
        pre_amount_current = 0
        if self.pk:
            pre_record = UserPoint.objects.filter(
                user=self.user, pk__lt=self.pk
            ).order_by('-pk').first()
        else:
            pre_record = UserPoint.objects.filter(
                user=self.user
            ).order_by('-pk').first()
        if pre_record:
            pre_amount_total = pre_record.amount_total
            pre_amount_current = pre_record.amount_current
        self.amount_current = int_value(pre_amount_current) + int_value(self.amount)
        if int_value(self.amount) > 0:
            self.amount_total = int_value(pre_amount_total) + int_value(self.amount)
        else:
            self.amount_total = pre_amount_total

    def update_user_point(self):
        # 更新用户的积分缓存数据
        key_name = 'app_wx_user_user_point_data'
        data = {
            'amount': int_value(self.amount),
            'amount_total': int_value(self.amount_total),
            'amount_current': int_value(self.amount_current),
        }
        hset_data(key_name, self.user_id, data)

    class Meta:
        ordering = ['-id']
        verbose_name = _('用户积分')
        verbose_name_plural = verbose_name

    def __str__(self):
        return "{0} {1}".format(self.user, self.amount)


@receiver(pre_save, sender=UserPoint)
def pre_save_user_point(sender, instance, **kwargs):
    instance.update_amount()


@receiver(post_save, sender=UserPoint)
def post_save_user_point(sender, instance, **kwargs):
    instance.update_user_point()


class UserAddress(models.Model):
    user = models.ForeignKey(
        WxUser,
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        verbose_name=_('用户')
    )
    name = models.CharField(verbose_name=_('收件人'), max_length=100, default='')
    mobile = models.CharField(verbose_name=_('手机号'), max_length=100, default='')

    address = models.CharField(verbose_name=_('城市'), max_length=500, null=True, blank=True)
    area = models.CharField(verbose_name=_('地区'), max_length=255, null=True, blank=True)

    default = models.BooleanField(verbose_name=_('默认'), default=True)

    datetime_created = models.DateTimeField(verbose_name=_('创建时间'), auto_now_add=True)
    datetime_updated = models.DateTimeField(verbose_name=_('更新时间'), auto_now=True)

    objects = models.Manager()

    class Meta:
        ordering = ['-id']
        verbose_name = _('用户地址')
        verbose_name_plural = verbose_name

    def __str__(self):
        return "{0} {1} {2} {3}".format(self.name, self.mobile, self.address, self.area)


class FeedBack(models.Model):
    user = models.ForeignKey(
        WxUser,
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        verbose_name=_('用户')
    )
    body = models.TextField(verbose_name=_('反馈内容'), max_length=2000, null=True, blank=True)
    is_checked = models.BooleanField(verbose_name='已查看', default=False)
    datetime_created = models.DateTimeField(verbose_name=_('创建时间'), auto_now_add=True)
    datetime_updated = models.DateTimeField(verbose_name=_('更新时间'), auto_now=True)

    objects = models.Manager()

    class Meta:
        ordering = ['-id']
        verbose_name = _('用户反馈')
        verbose_name_plural = verbose_name

    def __str__(self):
        return "{0}".format(self.body)


class SmsRecord(models.Model):
    mobile = models.CharField(verbose_name=_('手机号'), max_length=20)
    code = models.CharField(verbose_name=_('验证码'), max_length=10)
    is_active = models.BooleanField(verbose_name=_('有效的'), default=True)
    datetime_created = models.DateTimeField(verbose_name=_('创建时间'), auto_now_add=True)
    datetime_updated = models.DateTimeField(verbose_name=_('更新时间'), auto_now=True)

    objects = models.Manager()

    class Meta:
        ordering = ['-id']
        verbose_name = _('短信记录')
        verbose_name_plural = verbose_name

    def __str__(self):
        return "{} {}".format(self.mobile, self.code)


class Document(models.Model):
    title = models.CharField(verbose_name=_('标题'), max_length=255, default='')
    key_word = models.CharField(verbose_name=_('关键词'), max_length=255, default='')
    body = RichTextField(verbose_name=_('内容'), default='')
    is_active = models.BooleanField(verbose_name='有效的', default=True)

    datetime_created = models.DateTimeField(verbose_name=_('创建时间'), auto_now_add=True)
    datetime_updated = models.DateTimeField(verbose_name=_('更新时间'), auto_now=True)

    objects = models.Manager()

    class Meta:
        ordering = ['-id']
        verbose_name = _('文档管理')
        verbose_name_plural = verbose_name

    def __str__(self):
        return "{} {}".format(self.title, self.is_active)


def get_user_mobile_list(user_list):
    user_mobile_list = WxUser.objects.filter(
        pk__in=user_list
    ).values_list('mobile', flat=True)
    return user_mobile_list
